using System;
using System.Collections.Generic;
using System.Linq;
using RomanJendrusz.Amazon.ETL.Domain;
using RomanJendrusz.Amazon.ETL.Infrastructure.Bus;
using RomanJendrusz.Amazon.ETL.Infrastructure.Loging.Core;
using RomanJendrusz.Amazon.ETL.Messages;

namespace RomanJendrusz.Amazon.ETL.Services
{
    public class MarketPlaceService: IMarketPlaceService
    {
        private readonly IBus bus;

        public MarketPlaceService(IBus bus)
        {
            this.bus = bus;
        }

        public IList<SellerOffer> GetActualSellerOffersFor(Book book)
        {
            if (book == null) throw new ArgumentNullException("book");
            if (string.IsNullOrEmpty(book.Asin))
            {
                throw new InvalidOperationException("Can't search for a book with blank asin");
            }
            var countRequest = new GetBookOffersCountRequest { BookAsin = book.Asin, Condition = OffersCondition.All};
            var countResponse = bus.Process(countRequest).As<GetItemsCountResponse>();
            var bookOffersRequests = new List<GetBookOffersRequest>();
            for (int i = 1; i <= countResponse.PageCount; i++)
            {
                bookOffersRequests.Add(new GetBookOffersRequest { BookAsin = book.Asin, PageNumber = i, Condition = OffersCondition.All});
            }
            var sellerOffersResponses = bus.Process(bookOffersRequests.ToArray());
            var sellerOffers = new List<SellerOffer>();
            foreach (var response in sellerOffersResponses)
            {
                sellerOffers.AddRange(response.As<GetBookOffersResponse>().Offers);
            }
            sellerOffers.ForEach(o => o.Book = book);
            updateBookOfferDetails(sellerOffers);
            removeDuplicateSellers(sellerOffers);
            return sellerOffers;
        }

        private void removeDuplicateSellers(List<SellerOffer> offers)
        {
            IEnumerable<IGrouping<string, SellerOffer>> grouped = offers.Where(o=>o.Seller != null)
                .GroupBy(o => o.Seller.SellerId).Where(g => g.Count() > 1);
            foreach (var groupedOffers in grouped)
            {
                var list = groupedOffers.ToList();
                var seller= list[0].Seller;
                if (seller != null)
                {
                    list.ForEach(o=>o.Seller = seller);
                }
            }
        }

        private void updateBookOfferDetails(List<SellerOffer> sellerOffers)
        {
            int countBefore = sellerOffers.Count;
            sellerOffers.RemoveAll(s => s.ExchangeId == null || s.Seller == null);
            var removedCount = countBefore - sellerOffers.Count;
            if (removedCount != 0)
            {
                LogGateway.LogFor(GetType()).Warn(removedCount + " seller offers where removed");
            }
            var offerDetailsRequests = from offer in sellerOffers
                                       select new GetOfferDetailsRequest
                                       {
                                           SellerId = offer.Seller.SellerId,
                                           BookAsin = offer.Book.Asin,
                                           ExchangeId = offer.ExchangeId
                
                                       };
            AmazonResponse[] offerDetailsResponses;
            //try
            //{

                 offerDetailsResponses = bus.Process(offerDetailsRequests.ToArray());
            //}
            //catch (Exception ex)
            //{
            //    LogGateway.LogFor(GetType()).Error(ex.Message);
            //    return;
            //}
            foreach (var response in offerDetailsResponses)
            {
                var offerDetailsResponse = response.As<GetOfferDetailsResponse>();
                var offer = sellerOffers.Where(o => o.ExchangeId == offerDetailsResponse.ExchangeId).First();
                offer.StartDate = offerDetailsResponse.StartDate;
                offer.EndDate = offerDetailsResponse.EndDate;
            }
        }
    }
}